package com.system.vote.admin.security;

import cn.hutool.core.codec.Base64;
import com.alibaba.druid.util.StringUtils;
import com.system.vote.core.contant.JWTConstant;
import com.system.vote.admin.service.SysAccountService;
import com.system.vote.admin.service.impl.SysAccountServiceImpl;
import io.jsonwebtoken.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;
import java.util.logging.Logger;

/**
 * jwt加密和解密的工具类
 */
public class JwtUtil {

    private static final SysAccountService sysUserService=new SysAccountServiceImpl();
    private static  Logger logger=Logger.getLogger(JwtUtil.class.getName());
    /**
     * 签发JWT;这里创建的jwt
     *
     * @param subject 可以是JSON数据 尽可能少
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();  // 通过操作加密生成key
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主题
                .setIssuer("xc")// 签发者：小柴
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 过期时间
        }
        return builder.compact();
    }

    /**
     * 生成jwt token
     */
    public static String getJWTToken(String username) {
        return createJWT(username, username, 60 * 60 * 1000); // ttlMillis表示的是一小时
    }
    public static String getJWTToken(String uid, String username) {
        return createJWT(uid, username, 60 * 60 * 1000); // ttlMillis表示的是一小时
    }
    /**
     * 验证JWT
     * 根据验证时抛出的超时异常、签名异常、其他异常进行一定的操作
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        // 如果jwtStr为空的话，设置errcode为jwt不存在
        if (StringUtils.isEmpty(jwtStr)) {
            checkResult.setSuccess(false);
            checkResult.setErrCode(JWTConstant.JWT_ERRCODE_NULL);
            return checkResult;
        }
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(JWTConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(JWTConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }

    /**
     * 生成加密Key
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(JWTConstant.JWT_SECRET);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }


    /**
     * 解析JWT字符串
     *
     * @return 返回 jwt 解析后的 payload
     */
    public static Claims parseJWT(String jwt) {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

    public static String getCurrentUserName() {
        String token = null;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            token = request.getHeader("token");
            logger.info("token"+token);
            if (org.apache.commons.lang3.StringUtils.isBlank(token)) {
                token = request.getParameter("token");
            }
            if (org.apache.commons.lang3.StringUtils.isBlank(token)) {
                System.out.println("未登录");
            }
            Claims claims = parseJWT(token);
            return claims.getSubject();
        } catch (Exception e) {
            return null;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        String sc = createJWT("1", "小明", 60 * 60 * 1000);
        System.out.println(sc);
        System.out.println(validateJWT(sc).getErrCode());
        System.out.println(validateJWT(sc).getClaims().getId());
        System.out.println(validateJWT(sc).getClaims().getSubject());
        System.out.println(validateJWT(sc).getClaims());
        Claims claims = validateJWT(sc).getClaims();
        String sc2 = createJWT(claims.getId(), claims.getSubject(), JWTConstant.JWT_TTL);
        System.out.println(sc2);
    }
}